package cn.org.itool.ws.framework.netty.channel;

import cn.org.itool.common.constent.WsCodeEnum;
import cn.org.itool.ws.framework.netty.auth.Principal;
import cn.org.itool.ws.framework.netty.codec.*;
import cn.org.itool.ws.framework.utils.ChannelUtils;
import cn.org.itool.ws.framework.ws.WsServer;
import cn.org.itool.ws.template.AuthTemplate;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.http.websocketx.WebSocketFrameAggregator;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.log4j.Log4j2;

import java.util.Optional;

@Log4j2
@ChannelHandler.Sharable
public class WsAuthChannelInboundHandlerAdapter extends ChannelInboundHandlerAdapter {

    private final AuthTemplate AUTH_TEMPLATE = WsServer.AUTH_TEMPLATE;

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        System.out.println(evt.getClass().getSimpleName());
        super.userEventTriggered(ctx, evt);

        // 握手成功
        if(evt instanceof WebSocketServerProtocolHandler.HandshakeComplete complete) {
            String url = complete.requestUri();
            Optional<Principal> principalOpt = AUTH_TEMPLATE.getOptional(url);

            this.addHandler(ctx);

            if(principalOpt.isEmpty()){
                ChannelUtils.close(ctx.channel(), WsCodeEnum.AUTH_FAIL);
                return;
            }

            // 绑定用户信息
            AUTH_TEMPLATE.bindUser(principalOpt, ctx.channel());

            log.info("握手成功:{}", ctx.channel().id().asLongText());

        }
    }

    private void addHandler(ChannelHandlerContext ctx) {
        ChannelPipeline pipeline = ctx.pipeline();
        pipeline.remove("authorizationHandler");
        // 处理websocket 分帧情况, 报文最大长度为分帧最大长度 * 10
        pipeline.addLast(new WebSocketFrameAggregator(256 * 1024));
        pipeline.addLast(new WsTextDecoder());
        pipeline.addLast(new WsBinaryDecoder());
        pipeline.addLast("bizHeartbeatEncoder", new BizHeartbeatEncoder());
        pipeline.addLast("bizMessageEncoder", new BizMsgEncoder());
        pipeline.addLast("bizHandShakeEncoder", new BizHandShakeEncoder());
        pipeline.addLast("bizHandShakeAckEncoder", new BizHandShakeAckEncoder());
        pipeline.addLast("bizHandler", new BizHandler());
        pipeline.addLast("wsEventHandler", new WsEventHandler());
        pipeline.addLast("logger", new LoggingHandler());
    }
}
